package oop.controller.action.test;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import oop.controller.action.DefaultAction;
import oop.data.Answer;
import oop.data.BaseQuestion;
import oop.data.History;
import oop.data.Mix;
import oop.data.Question;
import oop.data.Test;
import oop.data.User;
import oop.db.dao.HistoryDAO;
import oop.db.dao.MixDAO;

import org.apache.commons.lang.ArrayUtils;

public class SolveAction extends DefaultAction {

	@Override
	public void perform() throws Exception {
		String submit = request.getParameter("submit");
		if ("done".equals(submit)) {

			Test test = (Test) request.getSession().getAttribute("test");
			Mix mix = MixDAO.create(null, test);

			Map<Long, long[]> choices = getChoices(test);
			double mark = getMark(test, choices);
			int time = Integer.parseInt(request.getParameter("time"));
			User user = (User) request.getSession().getAttribute("user");
			History history = HistoryDAO.create(user, mix.getId(), new Date(), mark,
					time, choices);

			setNextAction("history.view&id=" + history.getId());

		} else {

			int id = Integer.parseInt(request.getParameter("id"));
			Test test = Test.fetchById(id).get(0);
			Collections.shuffle(test.getQuestions());
			for (BaseQuestion question : test.getQuestions()) {
				Collections.shuffle(question.getAnswers());
			}
			request.getSession().setAttribute("test", test);

		}
	}

	private Map<Long, long[]> getChoices(Test test) {
		Map<Long, long[]> map = new HashMap<Long, long[]>();
		for (BaseQuestion question : test.getQuestions()) {
			String[] strs = request.getParameterValues("" + question.getId());
			if (ArrayUtils.isEmpty(strs)) {
				map.put(question.getId(), ArrayUtils.EMPTY_LONG_ARRAY);
			} else {
				long[] c = new long[strs.length];
				for (int i = 0; i < strs.length; i++) {
					try {
						c[i] = Long.parseLong(strs[i]);
					} catch (NumberFormatException ex) {
						//TODO ???
					}
				}
				Arrays.sort(c);
				map.put(question.getId(), c);
			}
		}
		return map;
	}

	private double getMark(Test test, Map<Long, long[]> choices) {
		double s = 0.0;
		for (int i = 0; i < test.getQuestions().size(); i++) {
			Question question = test.getQuestionById().get(i);
			long[] c = choices.get(question.getId());
			boolean correct = true;
			for (int j = 0; j < question.getAnswers().size(); j++) {
				Answer answer = question.getAnswerById().get(j);
				boolean choosed = Arrays.binarySearch(c, answer.getId()) >= 0;
				if (answer.isCorrect() != choosed) {
					correct = false;
					break;
				}
			}
			if (correct) {
				s += question.getMark();
			}
		}
		return s;
	}

}
